package com.wanke.client;

import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.WebSocket;
import io.vertx.core.http.WebSocketConnectOptions;
import io.vertx.core.http.WebSocketFrame;
import io.vertx.core.http.impl.headers.VertxHttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebsocketClient implements Handler<AsyncResult<WebSocket>> {

    private Vertx vertx;

    private WebSocket result;

    private HttpClient httpClient;

    private WebSocketConnectOptions options;

    private Handler<WebSocketFrame> readFrameHandler;

    private Logger logger = LoggerFactory.getLogger(WebsocketClient.class);

    public WebsocketClient(Vertx vertx, WebSocketConnectOptions options) {
        this.vertx = vertx;
        this.options = options;
        startClient(vertx,options);
        while (!isClosed()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                logger.error("",e);
            }
        }
    }

    public void startClient(Vertx vertx, WebSocketConnectOptions options) {
        httpClient = vertx.createHttpClient();
        Handler<AsyncResult<WebSocket>> asyncResultHandler = this::handle;
        httpClient.webSocket(options,asyncResultHandler);
    }

    @Override
    public void handle(AsyncResult<WebSocket> event) {
        result = ((AsyncResult<WebSocket>)event).result();
        if (event.succeeded()) {
            result = event.result();
            result.frameHandler(this.readFrameHandler);
            result.exceptionHandler((e) -> {
                logger.error("Restarting in 10 seconds");
                result.close();
                vertx.setTimer(10 * 1000, (__) -> {
                    this.startClient(vertx,options);
                });
            });
        } else {
            logger.error("",event.cause());
        }
    }

    public  void writeTextMessage(String text, Handler<AsyncResult<Void>> handler) {
        result.writeTextMessage(text , handler);
    }

    public  void reconnect(String accessToken){
        if (this.isClosed()) {
            VertxHttpHeaders entries = new VertxHttpHeaders();
            if (accessToken != null) {
                entries.set("access-token",accessToken);
            }
            options.setHeaders(entries);
            httpClient.webSocket(options,this::handle);
        }
    }

    public  void close(){
        if (!this.isClosed()) {
            result.close();
        }
    }
    public void setReaderHandler(Handler<WebSocketFrame> frameHandler) {
        if (this.getReadFrameHandler() == null && !this.isClosed()) {
            this.result.frameHandler(frameHandler);
            this.readFrameHandler = frameHandler;
        }
    }

    public Handler<WebSocketFrame> getReadFrameHandler() {
        return readFrameHandler;
    }

    public boolean isClosed() {
        return result == null || result.isClosed();
    }
}
